﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace EightNum
{
    public partial class Form1 : Form
    {
        public byte[,] tkey = new byte[,] { { 1, 2, 3 }, { 8, 0, 4 }, { 7, 6, 5 } };//目标状态
        public byte[,] pkey = new byte[,] { { 1, 2, 3 }, { 8, 0, 4 }, { 7, 6, 5 } };//当前状态

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~搜索需要定义的全局变量
        public static int tnum = 100000;//节点总数,控制能解决的问题难度
        public static int fnum = 1000;//1000;//关键路径总数
        public static int qfnum = 20000;//12000;//启发节点总数

        public Enode[] temple = new Enode[tnum];//临时存储所有搜索节点的节点数组！
        public Qfnode[] templeQf = new Qfnode[qfnum];//临时存储所有搜索节点的节点数组！

        public KeyArr[] fin = new KeyArr[fnum];//目标节点数组！

        public int tcount = 0;//计数节点个数！
        public int pathCount = 0;
        bool autoMoving = false;
        String sf;

        public int finc = -1;//目标状态的编号,记录最后一个目标所在的数组下标！
        public bool isOverFlow = false;//标识是否溢出
        public bool isComplete = false;

        public int finLength = 0;//fin目标节点的长度，创建完毕后更新

        EnAlgorithm algo;
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        public Form1()
        {
           InitializeComponent();
        }
       
        //--------------------------------------------------------------

        private void updateButton() {
            if (pkey[0, 0] != 0)
                this.label1.Text = pkey[0, 0].ToString();
            else
                this.label1.Text = "";
            if (pkey[0, 1] != 0)
                this.label2.Text = pkey[0, 1].ToString();
            else
                this.label2.Text = "";
            if (pkey[0, 2] != 0)
                this.label3.Text = pkey[0, 2].ToString();
            else
                this.label3.Text = "";
            if (pkey[1, 0] != 0)
                this.label4.Text = pkey[1, 0].ToString();
            else
                this.label4.Text = "";
            if (pkey[1, 1] != 0)
                this.label5.Text = pkey[1, 1].ToString();
            else
                this.label5.Text = "";
            if (pkey[1, 2] != 0)
                this.label6.Text = pkey[1, 2].ToString();
            else
                this.label6.Text = "";
            if (pkey[2, 0] != 0)
                this.label7.Text = pkey[2, 0].ToString();
            else
                this.label7.Text = "";
            if (pkey[2, 1] != 0)
                this.label8.Text = pkey[2, 1].ToString();
            else
                this.label8.Text = "";
            if (pkey[2, 2] != 0)
                this.label9.Text = pkey[2, 2].ToString();
            else
                this.label9.Text = "";
        }
       


        private void button1_Click(object sender, EventArgs e)
        {
            this.textBox1.Enabled = true;
            this.textBox2.Enabled = true;
            this.textBox3.Enabled = true;
            this.textBox4.Enabled = true;
            this.textBox5.Enabled = true;
            this.textBox6.Enabled = true;
            this.textBox7.Enabled = true;
            this.textBox8.Enabled = true;
            this.textBox9.Enabled = true;
            this.button5.Enabled = false;
          
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.textBox10.Text = "";
            String[] t = new String [9];
            t[0] = this.textBox1.Text;
            t[1] = this.textBox2.Text;
            t[2] = this.textBox3.Text;
            t[3] = this.textBox4.Text;
            t[4] = this.textBox5.Text;
            t[5] = this.textBox6.Text;
            t[6] = this.textBox7.Text;
            t[7] = this.textBox8.Text;
            t[8] = this.textBox9.Text;

            int m=0;
            for (int i = 0; i < 9; i++) {
                if (t[i] == "" || t[i] == " " || t[i] == "  ")
                    m = m + 9;
                else if (t[i] == "1")
                    m = m + 1;
                else if (t[i] == "2")
                    m = m + 2;
                else if (t[i] == "3")
                    m = m + 3;
                else if (t[i] == "4")
                    m = m + 4;
                else if (t[i] == "5")
                    m = m + 5;
                else if (t[i] == "6")
                    m = m + 6;
                else if (t[i] == "7")
                    m = m + 7;
                else if (t[i] == "8")
                    m = m + 8;
            }
            if (m == 45)
            {
                this.textBox1.Enabled = false;
                this.textBox2.Enabled = false;
                this.textBox3.Enabled = false;
                this.textBox4.Enabled = false;
                this.textBox5.Enabled = false;
                this.textBox6.Enabled = false;
                this.textBox7.Enabled = false;
                this.textBox8.Enabled = false;
                this.textBox9.Enabled = false;
                this.button5.Enabled = true;
                
               
                for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++) {
                        if (t[i * 3 + j] != "" && t[i * 3 + j] != " " && t[i * 3 + j] != "  ")
                        {
                            tkey[i, j] = Convert.ToByte(t[i * 3 + j]);
                        }
                        else
                        {
                            tkey[i, j] = 0;
                        }
                    }
            }
            else {
                MessageBox.Show("输入的目标状态不符合规范", "提醒", MessageBoxButtons.OK,MessageBoxIcon.Information);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            if (form2.ShowDialog() == System.Windows.Forms.DialogResult.OK) { 
                String[] t = new String[9];
                t = form2.getT();
                this.textBox10.Text = "";

                for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++)
                    {
                        if (t[i * 3 + j] != "" && t[i * 3 + j] != " " && t[i * 3 + j] != "  ")
                        {
                            pkey[i, j] = Convert.ToByte(t[i * 3 + j]);
                        }
                        else
                        {
                            pkey[i, j] = 0;
                        }
                    }
               
                this.label1.Text = t[0];
                this.label2.Text = t[1];
                this.label3.Text = t[2];
                this.label4.Text = t[3];
                this.label5.Text = t[4];
                this.label6.Text = t[5];
                this.label7.Text = t[6];
                this.label8.Text = t[7];
                this.label9.Text = t[8];
            }

            
        }

       

        private void button3_Click(object sender, EventArgs e)
        {
            int i = 0;
            int j = 0;
            Random ra = new Random(unchecked((int)DateTime.Now.Ticks));
            int num = ra.Next(1, 30);

            byte[,] t = new byte[3, 3];
            Utilities.makeEqule(t,tkey);
            this.textBox10.Text = "";

            int temp = 0;//临时变量，防止回走
            do
            {
                do
                {
                    j = ra.Next(1, 5);
                }
                while (j == temp);//如果回走就重新获取随机数

                switch (j)
                {
                    case 1:
                        {
                            if (Utilities.moveUp(t))
                            {
                                temp = 2;
                                i++;
                            }
                            break;
                        }
                    case 2:
                        {
                            if (Utilities.moveDown(t))
                            {
                                temp = 1;
                                i++;
                            }
                            break;
                        }
                    case 3:
                        {
                            if (Utilities.moveLeft(t))
                            {
                                temp = 4;
                                i++;
                            }
                            break;
                        }
                    case 4:
                        {
                            if (Utilities.moveRight(t))
                            {
                                temp = 3;
                                i++;
                            }
                            break;
                        }
                }

            }
            while (i != num);

            Utilities.makeEqule(pkey,t);
            updateButton();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (autoMoving == false)
            {
                this.button5.Text = "停止执行";
                this.autoMoving = true;

                this.button1.Enabled = false;
                this.button2.Enabled = false;
                this.button3.Enabled = false;
                this.button4.Enabled = false;
                

               

                if (!Utilities.checkHaveAnswer(pkey, tkey))
                {
                    MessageBox.Show("此问题无解！", "注意", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    this.button5.Text = "自动执行";
                    this.autoMoving = false;
                    this.button1.Enabled = true;
                    this.button2.Enabled = true;
                    this.button3.Enabled = true;
                    this.button4.Enabled = true;
                   
                }
                else
                {
                    algo = new EnAlgorithm(this);
                    long oldtime = DateTime.Now.Ticks;
                    if (this.radioButton1.Checked)//区分两种搜索方式
                    {
                        algo.getFinPathQf();
                        sf = "A星算法";
                    }
                    else
                    {
                        algo.getFinPathGd();
                        sf = "宽度优先算法";
                    }
                    double useTime = (DateTime.Now.Ticks - oldtime) / 10000000.0D;

                    if (this.isOverFlow)//查询后如果是溢出的情况
                    {
                        MessageBox.Show("错误类型:" + this.finc + " 超出计算范围！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        this.button5.Text = "自动执行";
                        this.autoMoving = false;
                        this.button1.Enabled = true;
                        this.button2.Enabled = true;
                        this.button3.Enabled = true;
                        this.button4.Enabled = true;
                      
                    }
                    else
                    {
                        this.pathCount = this.finLength - 1;//获取要走的路径长度
                      
                        MessageBox.Show("目标路径已找到，点击确定开始行动！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        
                        this.textBox10.Text = "";
                        this.textBox10.AppendText("用“" + this.sf + "”算法\r\n" + "解决该问题共使用" + (this.finLength - 1) + "步！\r\n花费时间" + useTime + "秒！\r\n");
                        this.timer1.Enabled = true;//开启时钟，开始行动

                    }
                }
            }
            else {
                this.button5.Text = "自动执行";
                this.autoMoving = false;

                this.timer1.Enabled = false;
                this.button1.Enabled = true;
                this.button2.Enabled = true;
                this.button3.Enabled = true;
                this.button4.Enabled = true;
                
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (this.pathCount > 0)//时钟跳动一下
            {
                for (int i = 0; i <= 2; i++)
                {
                    for (int j = 0; j <= 2; j++)
                    {
                        this.pkey[i, j] = this.fin[this.pathCount-1].k[i, j];
                    }
                }
                this.updateButton();//刷新按钮
                this.textBox10.AppendText(Utilities.stateStr(pkey));
                this.Refresh();//刷新界面
                this.pathCount--;
            }
            else
            {
                this.timer1.Enabled = false;//关闭时钟
                for (int i = 0; i <= 2; i++)
                {
                    for (int j = 0; j <= 2; j++)
                    {
                        this.pkey[i, j] = this.tkey[i, j];
                    }
                }
                MessageBox.Show("已为您完成目标,使用“" + this.sf + "”解决该难题一共用了 " + (this.finLength - 1) + " 步！", "温馨提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                
                this.button5.Text = "自动执行";
                this.autoMoving = false;
                this.button1.Enabled = true;
                this.button2.Enabled = true;
                this.button3.Enabled = true;
                this.button4.Enabled = true;
              
            }
        }

        private void button7_Click(object sender, EventArgs e)
        {
            this.timer1.Enabled = false;
            this.button1.Enabled = true;
            this.button2.Enabled = true;
            this.button3.Enabled = true;
            this.button4.Enabled = true;
           
        }

        private void button6_Click(object sender, EventArgs e)
        {
            if (!Utilities.checkHaveAnswer(pkey, tkey))
            {
                MessageBox.Show("此问题无解！", "注意", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            else
            {
                algo = new EnAlgorithm(this);
                if (this.radioButton1.Checked)//区分两种搜索方式
                {
                    algo.getFinPathQf();
                    sf = "A星算法";
                }
                else
                {
                    algo.getFinPathGd();
                    sf = "宽度优先算法";
                }
                if (this.isOverFlow)//查询后如果是溢出的情况
                {
                    MessageBox.Show("错误类型:" + this.finc + " 对不起，超出计算范围！", "温馨提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    this.Enabled = true;
                }

                this.pathCount = this.finLength - 1;//获取要走的路径长度
                if (this.pathCount > 0)//每点击一次
                {
                    for (int i = 0; i <= 2; i++)
                    {
                        for (int j = 0; j <= 2; j++)
                        {
                            this.pkey[i, j] = this.fin[pathCount - 1].k[i, j];
                        }
                    }
                    this.updateButton();//刷新按钮
                    this.textBox10.AppendText(Utilities.stateStr(pkey));
                    this.Refresh();//刷新界面
                    this.pathCount--;
                }
                else if (this.pathCount == 0)
                {
                    for (int i = 0; i <= 2; i++)
                    {
                        for (int j = 0; j <= 2; j++)
                        {
                            this.pkey[i, j] = this.tkey[i, j];
                        }
                    }
                    MessageBox.Show("已经到达目标状态！", "温馨提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                   
                }
            }
        }

        private void checkBox1_Click(object sender, EventArgs e)
        {
            if (this.checkBox1.Checked == true)
            {
                this.checkBox1.Checked = false;
                this.checkBox1.CheckState = CheckState.Unchecked;
            }
            else
            {
                this.checkBox1.Checked = true;
                this.checkBox1.CheckState = CheckState.Checked;
            }           
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (this.checkBox1.Checked == true)
            {                
                this.textBox10.Visible = true;
            }
            else
            {
                
                this.textBox10.Visible = false;
            }
        }

        private void textBox10_TextChanged(object sender, EventArgs e)
        {
            textBox10.ScrollToCaret();
        }
    }
}
